package com.typhoon.spring_jdbctemplate.retry;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.*;

//@Service
public class AutoRefundManager implements InitializingBean {

    private static int MAX_RETRY_TIME = 3;

    /**
     * 线程池
     */
    ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3);

    Map<String,BlockingDeque<AutoRefundContext>> map = new HashMap<>();

    private static final String queue1 = "QUEUE1";
    private static final String queue2 = "QUEUE2";


    @PostConstruct
    public  void init () {
        this.startRetrySchedule();
    }

    private void startRetrySchedule() {
        long initDelay = 0;
        long delay = 10;//定时10分钟
        //加载DB数据到q2
        executorService.scheduleWithFixedDelay(() -> {
            System.out.println("加载DB数据到q2");
        },initDelay,delay,TimeUnit.SECONDS);
        executorService.scheduleWithFixedDelay(() -> {
            System.out.println("从q1消费数据");
        },initDelay,delay,TimeUnit.SECONDS);
        executorService.scheduleWithFixedDelay(() -> {
            System.out.println("从q2消费数据");
        },initDelay,delay,TimeUnit.SECONDS);
    }

    /**
     * 自动退
     */
    public void autoRefund(AutoRefundContext autoRefundContext) {
        this.autoRefund(autoRefundContext,map.get(queue1));
    }

    private void autoRefund(AutoRefundContext autoRefundContext,BlockingDeque queue) {
        try {
            this.doAutoRefund(autoRefundContext.getRefundId());
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("发生异常");
            this.enqueue(autoRefundContext,queue);
        }

    }

    /**
     * 入队
     * @param autoRefundContext
     * @param queue
     */
    private void enqueue(AutoRefundContext autoRefundContext,BlockingDeque queue) {
        BlockingDeque<AutoRefundContext> q1 = map.get(queue1);
        BlockingDeque<AutoRefundContext> q2 = map.get(queue2);
        int retryTiems = autoRefundContext.getRetryTimes();
        if(retryTiems > MAX_RETRY_TIME) {
            if(q1.equals(queue)) {//队列1
                System.out.println("持久化到DB");
            } else if(q2.equals(queue)) {//队列2
                System.out.println("预警");
            } else {
                throw new RuntimeException("error occurs");
            }
            return;
        }
        retryTiems += 1;
        try {
            autoRefundContext.setRetryTimes(retryTiems);
            queue.offer(autoRefundContext);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 自动退操作
     * @param refundId
     */
    private void doAutoRefund(Long refundId) {
        Random random = new Random();
        if(random.nextBoolean() == false) {
            throw new RuntimeException("自动退款异常");
        }
    }


    /**
     * 初始化两个队列
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        map.put(queue1,new LinkedBlockingDeque(100));
        map.put(queue2,new LinkedBlockingDeque(100));
    }
}
